﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using Microsoft.WindowsMobile.PocketOutlook;
using System.Windows.Forms;
using System.Threading;
using Microsoft.WindowsMobile.Telephony;
using System.Xml.Serialization;
using OCDStudio.SMSPPP.Common.Mobile;
using System.Xml;

namespace OCDStudio.SMSPPP.WindowsMobile.Server
{
    class SMSPPPClientHandler
    {

        private TcpClient client;
        private SMSPPPMobileServer server;
        private int defaultSmsSleepTime;

        public SMSPPPClientHandler(SMSPPPMobileServer serv, TcpClient cl)
        {
            this.client = cl;
            this.server = serv;
            this.defaultSmsSleepTime = Int32.Parse(
                global::OCDStudio.SMSPPP.WindowsMobile.Server.Properties.Resources.DefaultSMSSleepTime);
        }

        public void ManageTcpClient() {
            NetworkStream str = client.GetStream();
            StreamReader reader = new StreamReader(str);
            StreamWriter writer = new StreamWriter(str);
            try
            {
                while (true)
                {
                    SMSPPPCommandsResponses resp = ManageCommand(reader.ReadLine());
                    writer.WriteLine(resp);
                    writer.Flush();                
                }
            }
            catch (Exception e)
            {
                client.Close();                                
            }
        }

        private SMSPPPCommandsResponses ManageCommand(string p)
        {
            string[] message = p.Split(SMSPPPConstants.COMMAND_BODY_SEPARATOR.ToCharArray()[0]);

            XmlSerializer s = new XmlSerializer(typeof(SMSPPPCommandBody));
            TextReader reader = new StringReader(message[1]);

            SMSPPPCommandBody body = null;
            try
            {
                body = (SMSPPPCommandBody)s.Deserialize(reader);
            }
            catch {                 
                body = new SMSPPPCommandBody();
            }

            
            SMSPPPCommands command = (SMSPPPCommands)Enum.Parse(typeof(SMSPPPCommands),message[0],true);

            switch (command)
            {
                case SMSPPPCommands.HEARTBEAT:
                    return SMSPPPCommandsResponses.HEARTBEAT_OK;
                case SMSPPPCommands.SEND_SMS:
                    if (body.Parameters.Count == 0) return SMSPPPCommandsResponses.WRONG_MESSAGE_FORMAT;
                    else
                    {
                        new Thread(new ThreadStart(new ThreadStartDelegateWrapper(
                            body,this.ManageSms).Worker)).Start();                        
                        return SMSPPPCommandsResponses.MESSAGE_RECEIVED;                        
                    }
                   
                case SMSPPPCommands.PHONE_CALL:
                    if (body.Parameters.Count == 0) return SMSPPPCommandsResponses.WRONG_MESSAGE_FORMAT;
                    else
                    {
                        new Thread(new ThreadStart(new ThreadStartDelegateWrapper(
                            body,this.ManagePhoneCall).Worker)).Start();
                        return SMSPPPCommandsResponses.MESSAGE_RECEIVED;
                    }
                   
            }

            return SMSPPPCommandsResponses.COMMAND_NOT_UNDERSTOOD;

        }

        private void ManagePhoneCall(SMSPPPCommandBody body)
        {
            string number = body.Parameters[0].Value;
            Phone p = new Phone();
            p.Talk(number);
            
        }

        private void ManageSms(SMSPPPCommandBody body)
        {            
            foreach (NameValue current in body.Parameters)
            {
                
                string dest, text;
                dest = current.Name;
                text = current.Value;
                try
                {
                    server.Session.SmsAccount.Send(new SmsMessage(dest, text));
                    short fragments = (short)(((short)(text.Length / 160)) + 1);
                    server.SmsLog.Insert(dest, text, fragments, DateTime.Now);
                    Thread.Sleep(defaultSmsSleepTime);
                }
                catch
                {
                    continue;
                }
            }
            
        }

        

    }

    delegate void ManagementOperation(SMSPPPCommandBody body);

    class ThreadStartDelegateWrapper
    {
        private SMSPPPCommandBody messageBody;
        private ManagementOperation operation;

        

        public ThreadStartDelegateWrapper(SMSPPPCommandBody body,ManagementOperation op)
        {
            this.messageBody = body;
            this.operation = op;
        }

        
        public void Worker()
        {
            operation.Invoke(messageBody);
        }
    } 


}
